package com.sisgesbyte.web.managedBean.proyeccion;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpSession;

import org.primefaces.model.DefaultTreeNode;
import org.primefaces.model.TreeNode;

import com.sisgesbyte.common.ConstantesInternasSistema;
import com.sisgesbyte.dao.beanDao.FiltrosBean;
import com.sisgesbyte.dao.beanDao.FiltrosSQLBean;
import com.sisgesbyte.services.proyeccion.MantProyeccionFfvvService;
import com.sisgesbyte.services.proyeccion.bean.FiltroOpcionesFFVVBean;
import com.sisgesbyte.services.proyeccion.bean.ListaProyFfvvCategoriaResponse;
import com.sisgesbyte.services.proyeccion.bean.ProyGeneralCategoriaBean;
import com.sisgesbyte.services.ventas.MantEstructuraVentaService;
import com.sisgesbyte.services.ventas.MantenimientoFFVVService;
import com.sisgesbyte.services.ventas.MantenimientoPeriodo;
import com.sisgesbyte.services.ventas.bean.EstructuraVentaFO;
import com.sisgesbyte.services.ventas.bean.EstruturaVentaBean;
import com.sisgesbyte.services.ventas.bean.FFVVBean;
import com.sisgesbyte.services.ventas.bean.ListaEstructuraVentaResponse;
import com.sisgesbyte.services.ventas.bean.ListaFFVVJerarquiaResponse;
import com.sisgesbyte.services.ventas.bean.PeriodoBean;
import com.sisgesbyte.services.ventas.bean.PeriodoListaBean;

@ManagedBean
@ViewScoped
public class ResumenProyFfvvCategoriaMBean implements Serializable {

	private static final long serialVersionUID = 1L;

	@EJB
	private MantProyeccionFfvvService mantProyeccionFfvvService;
	@EJB
	private MantenimientoFFVVService mantenimientoFFVVService;
	@EJB
	private MantEstructuraVentaService mantEstructuraVentaService;
	@EJB
	private MantenimientoPeriodo mantenimientoPeriodo;
	private List<ProyGeneralCategoriaBean> listaProyFfvvCategoria;
	private List<PeriodoBean> listaPeriodos;
	private List<EstruturaVentaBean> listaEstructuraVenta;
	private List<FFVVBean> listaJerarquiaFFVV;
	private int periodoDefault;
	private int idEstructuraVenta;
	private int idFfvv;
	private String totalMarcas;
	private TreeNode selectedNode;
	private TreeNode root;
	private TreeNode[] node;
	private List<ProyGeneralCategoriaBean> listaCategoriaPadres;
	private List<ProyGeneralCategoriaBean> listaCategoriaHijos;
	private Map<Integer, Integer> auxNumNode;
	private int numNode;
	
	@PostConstruct
	private void init() {
		cargarPeriodos();
		mostrarPeriodoDefault();
		cargarEstructuraVenta();
		root = new DefaultTreeNode("Root", null);
	}
	
	public void inicializar(){
		listaCategoriaPadres = new ArrayList<ProyGeneralCategoriaBean>();
		listaCategoriaHijos = new ArrayList<ProyGeneralCategoriaBean>();
		auxNumNode = new HashMap<Integer, Integer>();
		numNode = 0;
		root = new DefaultTreeNode("Root", null);
		try {
			FiltroOpcionesFFVVBean bean = new FiltroOpcionesFFVVBean();
			bean.setIdFfvv(idFfvv);
			bean.setIdPeriodo(periodoDefault);
			ListaProyFfvvCategoriaResponse response = mantProyeccionFfvvService.mostrarProyFfvvCategoria(ObtenerIdTransaccion(),bean);
			if(response.getCodigoRespuesta().equalsIgnoreCase(ConstantesInternasSistema.CODIGO_EXITO)){
				listaCategoriaPadres = new ArrayList<ProyGeneralCategoriaBean>();
				listaCategoriaHijos = new ArrayList<ProyGeneralCategoriaBean>();
				for (ProyGeneralCategoriaBean ls : response.getListaProyFfvvCategoria()) {
					if (ls.getIdPadre() == 0) {
						listaCategoriaPadres.add(ls);
					} else {
						listaCategoriaHijos.add(ls);
					}
				}
				int max = response.getListaProyFfvvCategoria().size();
				if (max > 0) {
					node = new TreeNode[max];
					for (ProyGeneralCategoriaBean ls : listaCategoriaPadres) {
						node[numNode] = new DefaultTreeNode(ls, root);
						auxNumNode.put(ls.getId(), numNode);
						numNode++;
						assignChildren(ls);
					}
				}
			}else{
				System.out.println("No se obtuvo resultados ");
				root = new DefaultTreeNode("Root", null);
			}
			
		} catch (Exception e) {
			root = new DefaultTreeNode("Root", null);
			System.out.println("Error al cargar los periodos: " + e);
		}
	}
	
	public void cargarPeriodos() {
		try {
			PeriodoListaBean periodos = mantenimientoPeriodo.listaPeriodos(ObtenerIdTransaccion());
			this.listaPeriodos = periodos.getListaPeriodos();
		} catch (Exception e) {
			System.out.println("Error al cargar los periodos: " + e);
		}
	}
	public void mostrarPeriodoDefault() {
		for (PeriodoBean ls : getListaPeriodos()) {
			if (ls.getDefecto() != null && ls.getDefecto() == true) {
				setPeriodoDefault(ls.getId());
			}
		}
	}
	
	public void cargarEstructuraVenta(){
		try{
			EstructuraVentaFO filtroOpciones = new EstructuraVentaFO();
			filtroOpciones.setActive(true);
			filtroOpciones.setTxtBuscar(null);
			ListaEstructuraVentaResponse response = mantEstructuraVentaService.mostrarEstructuraVenta(ObtenerIdTransaccion(), filtroOpciones);
			if(response.getCodigoRespuesta().equalsIgnoreCase(ConstantesInternasSistema.CODIGO_EXITO)){
				this.listaEstructuraVenta = response.getListaEstructuraVenta();
			}else{
				this.listaEstructuraVenta = new ArrayList<EstruturaVentaBean>();
			}
		}catch(Exception e){
			System.out.println("Error al listar Estructura de ventas " + e);
			this.listaEstructuraVenta = new ArrayList<EstruturaVentaBean>();
		}
	}
	public void cargarFFvv(){
		
		if(idEstructuraVenta < 1){
			System.out.println("Debe seleccionar la estructura de venta ");
			return;
		}
		try{
			FiltrosSQLBean filtroSQL = new FiltrosSQLBean();
			List<Object> valores = new ArrayList<>();
			List<FiltrosBean> filtro = new ArrayList<FiltrosBean>();
				FiltrosBean filtroFfvv = new FiltrosBean();
				List<String> campoFfvv = new ArrayList<String>();
				campoFfvv.add("ee.estructura_venta_id");
				campoFfvv.add("ee.active");
				filtroFfvv.setCampos(campoFfvv);
				filtroFfvv.setOperador("=");
				filtro.add(filtroFfvv);
				valores.add(idEstructuraVenta);
				valores.add(true);

			filtroSQL.setListaFiltros(filtro);
			filtroSQL.setListaValores(valores);
			ListaFFVVJerarquiaResponse response = mantenimientoFFVVService.listaFFVV(ObtenerIdTransaccion(), filtroSQL);
			if(response.getCodigoRespuesta().equalsIgnoreCase(ConstantesInternasSistema.CODIGO_EXITO)){
				this.listaJerarquiaFFVV = response.getListaJerarquiaFFVV();
			}else{
				this.listaJerarquiaFFVV = new ArrayList<FFVVBean>();
			}
		}catch(Exception e){
			System.out.println("Error al cargar la lista de FFVV " + e);
			this.listaJerarquiaFFVV = new ArrayList<FFVVBean>();
		}
	}
	/**
	 * Establece los nodos hijos a un árbol menu de forma recursiva.
	 * 
	 * @param father
	 *            El nodo padre.
	 */
	private void assignChildren(ProyGeneralCategoriaBean father) {
		List<ProyGeneralCategoriaBean> children = new ArrayList<ProyGeneralCategoriaBean>();
		children = getMenuByFather(father);
		Iterator<ProyGeneralCategoriaBean> iter = children.iterator();

		while (iter.hasNext()) {
			ProyGeneralCategoriaBean child = iter.next();
			node[numNode] = new DefaultTreeNode("document", child,
					node[auxNumNode.get(father.getId())]);
			auxNumNode.put(child.getId(), numNode);
			numNode++;
			assignChildren(child);
		}
	}

	/**
	 * Devuelve una lista de nodos según su padre.
	 * 
	 * @param father
	 *            El nodo padre.
	 * @return La lista de nodos.
	 */
	private List<ProyGeneralCategoriaBean> getMenuByFather(
			ProyGeneralCategoriaBean father) {

		List<ProyGeneralCategoriaBean> listR = new ArrayList<ProyGeneralCategoriaBean>();
		Iterator<ProyGeneralCategoriaBean> it = listaCategoriaHijos.iterator();
		while (it.hasNext()) {
			ProyGeneralCategoriaBean me = it.next();
			if (me.getIdPadre().intValue() == father.getId()) {
				listR.add(me);
				it.remove();
			}
		}
		return listR;
	}
	public String ObtenerIdTransaccion() {
		FacesContext fCtx = FacesContext.getCurrentInstance();
		HttpSession session = (HttpSession) fCtx.getExternalContext()
				.getSession(false);
		String sessionId = session.getId().replace(".undefined", "");
		return sessionId;
	}
	public List<ProyGeneralCategoriaBean> getListaProyFfvvCategoria() {
		return listaProyFfvvCategoria;
	}

	public void setListaProyFfvvCategoria(
			List<ProyGeneralCategoriaBean> listaProyFfvvCategoria) {
		this.listaProyFfvvCategoria = listaProyFfvvCategoria;
	}

	public List<PeriodoBean> getListaPeriodos() {
		return listaPeriodos;
	}

	public void setListaPeriodos(List<PeriodoBean> listaPeriodos) {
		this.listaPeriodos = listaPeriodos;
	}

	public List<EstruturaVentaBean> getListaEstructuraVenta() {
		return listaEstructuraVenta;
	}

	public void setListaEstructuraVenta(
			List<EstruturaVentaBean> listaEstructuraVenta) {
		this.listaEstructuraVenta = listaEstructuraVenta;
	}

	public List<FFVVBean> getListaJerarquiaFFVV() {
		return listaJerarquiaFFVV;
	}

	public void setListaJerarquiaFFVV(List<FFVVBean> listaJerarquiaFFVV) {
		this.listaJerarquiaFFVV = listaJerarquiaFFVV;
	}

	public int getPeriodoDefault() {
		return periodoDefault;
	}

	public void setPeriodoDefault(int periodoDefault) {
		this.periodoDefault = periodoDefault;
	}

	public int getIdEstructuraVenta() {
		return idEstructuraVenta;
	}

	public void setIdEstructuraVenta(int idEstructuraVenta) {
		this.idEstructuraVenta = idEstructuraVenta;
	}

	public int getIdFfvv() {
		return idFfvv;
	}

	public void setIdFfvv(int idFfvv) {
		this.idFfvv = idFfvv;
	}

	public String getTotalMarcas() {
		return totalMarcas;
	}

	public void setTotalMarcas(String totalMarcas) {
		this.totalMarcas = totalMarcas;
	}

	public TreeNode getSelectedNode() {
		return selectedNode;
	}

	public void setSelectedNode(TreeNode selectedNode) {
		this.selectedNode = selectedNode;
	}

	public TreeNode getRoot() {
		return root;
	}

	public void setRoot(TreeNode root) {
		this.root = root;
	}

}
